﻿using Fizzler.Systems.HtmlAgilityPack;
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HuaJuanAudioNevolDown
{
    public class ExtraLeting8Com : IExtractor
    {
        private static readonly HttpClient client = new HttpClient();

        public string Site => "https://www.leting8.com";
        string siteSearchPath = "/search.php";
        int htmlRequestDelay = 100;
        public DataTable _novelData { get; set; }
        public ToolStripProgressBar _pbRequestProcess { get; set; }
        public string NovelName { get; set; }
        public string NovelRealHost { get; set; }
        public Form _form { get; set; }
        public async Task ExtractAudioLinksAsync(string novelName, string url)
        {
            this.NovelName = novelName;

            int index = 0;
            // 取得域名网址
            string host = Utils.GetHost(url);

            // 取得root doc node
            var docNode = GetDocumentNode(url);
            List<PageInfo> pages = GetPages(docNode);

            _pbRequestProcess.Minimum = 0;
            _pbRequestProcess.Maximum = pages.Count;
            // 循环每一页
            for (int i = 0; i < pages.Count; i++)
            {
                var page = pages[i];
                var pageUrl = Site + page.Link;
                var chapterNode = GetDocumentNode(pageUrl);
                var chapters = GetChapterLinks(chapterNode);

                for (int j = 0; j < chapters.Count; j++)
                {
                    index++;
                    var info = chapters[j];
                    UpdateListView(index, page.Name, info.AudioName, info.ReqAudioUrl, info.RealAudioUrl, ExtractorStatus.Waiting.GetDescription());
                }
                _pbRequestProcess.Value = i + 1;
                await Task.Delay(htmlRequestDelay);
            }

            _pbRequestProcess.Minimum = 0;
            _pbRequestProcess.Maximum = _novelData.Rows.Count;

            // 用于存放和控制并发任务的列表
            List<Task> taskList = new List<Task>();
            int maxConcurrentTasks = 10;

            for (int j = 0; j < _novelData.Rows.Count; j++)
            {
                DataRow row = _novelData.Rows[j];
                string realUrl = "";

                if (taskList.Count >= maxConcurrentTasks)
                {
                    Task completedTask = await Task.WhenAny(taskList);
                    taskList.Remove(completedTask);

                    UpdateProgressBar(j + 1);
                }

                var task = Task.Run(async () =>
                {
                    for (int k = 0; k < 3; k++)
                    {
                        realUrl = await GetMp3UrlAsync(row["ReqAddress"].ToString());

                        lock (_novelData)
                        {
                            if (realUrl == "")
                            {
                                row["ExtractorStatus"] = ExtractorStatus.Failure.GetDescription();
                                continue;
                            }
                            else
                            {
                                row["RealAddress"] = Uri.EscapeUriString(NovelRealHost + realUrl);
                                row["ExtractorStatus"] = ExtractorStatus.Sucess.GetDescription();
                                break;
                            }
                        }
                    }
                    _pbRequestProcess.Value = j + 1;
                });

                taskList.Add(task);
            }
            await Task.WhenAll(taskList);
            UpdateProgressBar(_novelData.Rows.Count);
        }
        private void UpdateProgressBar(int value)
        {
            if (_form.InvokeRequired)
            {
                _form.Invoke(new Action(() => _pbRequestProcess.Value = value));
            }
            else
            {
                _pbRequestProcess.Value = value;
            }
        }

        public async Task ReExtractAudioLinksAsync(DataGridViewSelectedRowCollection SelectedRows)
        {
            for (int j = 0; j < SelectedRows.Count; j++)
            {
                DataGridViewRow row = SelectedRows[j];

                string realUrl = "";
                if (row.Cells["ExtractorStatus"].Value.ToString() != ExtractorStatus.Sucess.GetDescription())
                {
                    // 正常一次+重试两次，共计3次
                    for (int k = 0; k < 3; k++)
                    {
                        realUrl = await GetMp3UrlAsync(row.Cells["ReqAddress"].Value.ToString());
                        if (realUrl == "")
                        {
                            row.Cells["ExtractorStatus"].Value = ExtractorStatus.Failure.GetDescription();
                            continue;
                        }
                        else
                        {
                            row.Cells["RealAddress"].Value = Uri.EscapeUriString(NovelRealHost + realUrl);
                            row.Cells["ExtractorStatus"].Value = ExtractorStatus.Sucess.GetDescription();
                            break;
                        }
                    }
                }
                await Task.Delay(htmlRequestDelay);
            }
        }

        public async Task<List<SearchResultInfo>> Search(string searchtype, string searchword)
        {
            List<SearchResultInfo> searchResultInfos = new List<SearchResultInfo>();

            var url = $"{Site}{siteSearchPath.Replace("{0}", "1").Replace("{1}", searchword)}";
            url = Uri.EscapeUriString(url);

            var docNode = GetDocumentNode(url);

            var resultListNode = docNode.QuerySelectorAll(".box-list-item-text").ToList();

            if (resultListNode.Count > 0)
            {
                for (int i = 0; i < resultListNode.Count; i++)
                {
                    var node = resultListNode[i];

                    // 提取书名和链接
                    var titleNode = node.QuerySelector(".box-list-item-text-title a");
                    string novelName = titleNode.InnerText.Trim();
                    string novelAddress = titleNode.GetAttributeValue("href", "").Trim();

                    // 提取作者
                    var authorNode = node.QuerySelector(".lnr-user + span a");
                    string novelAuthor = authorNode.InnerText.Trim();

                    // 提取主播
                    var anchorNode = node.QuerySelector(".lnr-mic + span a");
                    string NovelAnchor = anchorNode.InnerText.Trim();

                    // 提取简介
                    var introNode = node.QuerySelector(".box-list-item-text-intro");
                    string intro = introNode.InnerText.Trim();

                    searchResultInfos.Add(new SearchResultInfo()
                    {
                        Site = this.Site,
                        NovelName = novelName,
                        NovelAuthor = novelAuthor,
                        NovelAnchor = NovelAnchor,
                        NovelAddress = Site + novelAddress,
                        Novelintro = intro,
                    });
                    await Task.Delay(1);
                }
            }
            return searchResultInfos;
        }

        private HtmlNode GetDocumentNodeWithHtml(string html)
        {
            // 创建 HtmlDocument 实例
            var doc = new HtmlAgilityPack.HtmlDocument();

            // 加载 HTML 字符串
            doc.LoadHtml(html);

            // 返回根节点（document.DocumentNode）
            return doc.DocumentNode;
        }

        private HtmlNode GetDocumentNode(string url)
        {
            var web = new HtmlWeb();
            var doc = web.Load(url);
            return doc.DocumentNode;
        }

        private List<PageInfo> GetPages(HtmlNode pageNode)
        {
            var optionNodes = pageNode.QuerySelectorAll(".hd-sel select option").ToList();
            List<PageInfo> pages = new List<PageInfo>();
            foreach (var option in optionNodes)
            {
                // 获取每个 <option> 的 value 属性
                var link = option.GetAttributeValue("value", string.Empty);
                if (!link.EndsWith("html"))
                {
                    link += "p1.html";
                }
                var name = option.InnerText.Trim();
                pages.Add(new PageInfo() { Name = name, Link = link });
            }
            return pages;
        }

        private List<ChapterInfo> GetChapterLinks(HtmlNode chapterNode)
        {
            List<ChapterInfo> Mp3InfoList = new List<ChapterInfo>();
            List<HtmlNode> item = chapterNode.QuerySelectorAll("#playlist li a").ToList();

            for (int i = 0; i < item.Count; i++)
            {
                var node = item[i];
                string link = node.GetAttributeValue("href", "");
                string name = node.InnerText;
                name = Regex.Replace(name, "\r\n", "");
                name = name.Trim();
                Mp3InfoList.Add(new ChapterInfo()
                {
                    ReqAudioUrl = Site + link,
                    AudioName = name
                });
            }
            return Mp3InfoList;
        }

        private void UpdateListView(int index, string chatper, string chapterName, string reqUrl, string mp3Url, string status)
        {
            DataRow row = _novelData.NewRow();
            row["Index"] = index.ToString();
            row["ChapterName"] = chapterName;
            row["ReqAddress"] = reqUrl;
            row["RealAddress"] = mp3Url;
            row["ExtractorStatus"] = status;
            _novelData.Rows.Add(row);
        }

        public async Task<string> GetMp3UrlAsync(string url)
        {
            string audioSrc = "";
            var parentDocNode = GetDocumentNode(url);

            try
            {
                // 找到 <iframe> 标签
                var iframeNode = parentDocNode.QuerySelector("iframe");

                if (iframeNode != null)
                {
                    string iframeSrc = iframeNode.GetAttributeValue("src", string.Empty);

                    if (!string.IsNullOrEmpty(iframeSrc))
                    {
                        var iframeContent = await client.GetStringAsync(Site + iframeSrc);
                        audioSrc = GetAudioUrl(iframeContent);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return audioSrc;
        }
    }
}
